#include <stdio.h>
#include <sys/socket.h>    // socket()
#include <netinet/ether.h> // ETH_P_ALL
#include <unistd.h>        // close
#include <arpa/inet.h>     // htons
#include <string.h>        // memset
#include <net/ethernet.h>  // struct ether_header
#include <stdlib.h>        // malloc
#include <signal.h>
#include "get_interface.h"
#include "arp_handle.h"
#include "tools.h"
#include "ip_handle.h"
#include "thread_pool.h"
#include "filter.h"

static int end = 0; // 退出标识
void stop_func(int sig)
{
    end = 1; // 退出循环
}

/*******************************************************
函数: int main(int argc, char const *argv[])
功能: 主函数
参数: 无
返回值: 无
********************************************************/
int main(int argc, char const *argv[])
{
    // 创建原始套接字
    int sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); // 接收所有协议
    if (sockfd < 0)
    {
        perror("socket");
        return -1;
    }

    // 获取本地网卡信息
    if (getinterface(sockfd) < 0) // 返回0成功
    {
        perror("getinterface");
        return -1;
    }

    // int count = get_interface_num(); // 获取本地网卡数量
    arp_list_head *arp_hdr = init_arp_list_head(); // 初始化arp链表
    if (arp_hdr == NULL)
    {
        printf("init_arp_list_head\n");
        return -1;
    }

    // 初始化线程池
    threadpool_t pool;
    if (init_thread_pool(&pool, 30))
    {
        perror("init_thread_pool");
        return -1;
    }

    // 完整帧数据
    unsigned char buf[MAXDATASIZE];
    ssize_t len = 0; // 获取读取到的数据长度

    // 监听停止信号
    signal(SIGINT, stop_func);
    // 开启操作系统
    char *file_name = "./config.txt";
    threadpool_add_task(&pool, filter_handler, (void*)file_name);

    while (1)
    {
        if (end) // 退出程序标识
        {
            break;
        }
        memset(buf, 0, sizeof(buf));
        len = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);
        if (len <= 0 || len > MAXDATASIZE) // 如果数据小于等于0说明有错误信息,如果数据长度大于1500处理不了
        {
            perror("recvfrom");
            continue;
        }

        // 获取mac报文
        // struct ether_header* eth_hdr = (struct ether_header*)buf; // 可以使用结构体获取 需要<net/ethernet.h>
        // ntohs(eth_hdr->ether_type) // 协议类型
        // 这里根据字节取mac头部 目的mac 6B 源mac 6B 协议 2B
        unsigned short mac_type = ntohs(*(unsigned short *)(buf + 12));
        if (mac_type == 0x0806) // ARP报文
        {
            raw_msg *arp_data = (raw_msg *)malloc(sizeof(raw_msg)); // 申请空间保存所需数据
            if (NULL == arp_data)                                   // 如果空间申请失败
            {
                perror("malloc");
                continue;
            }
            memset(arp_data, 0, sizeof(raw_msg));                   // 清空
            arp_data->fd = sockfd;                                  // 描述符
            memcpy(arp_data->data, buf, len);                       // 原始报文
            arp_data->data_len = len;                               // 报文长度
            threadpool_add_task(&pool, arp_recv, (void *)arp_data); // 线程池添加任务
        }
        else if (mac_type == 0x0800) // IP报文
        {
            raw_msg *ip_data = (raw_msg *)malloc(sizeof(raw_msg)); // 申请空间保存所需数据
            if (NULL == ip_data)                                   // 如果空间申请失败
            {
                perror("malloc");
                continue;
            }
            memset(ip_data, 0, sizeof(raw_msg));                  // 清空
            ip_data->fd = sockfd;                                 // 描述符
            memcpy(ip_data->data, buf, len);                      // 原始报文
            ip_data->data_len = len;                              // 报文长度
            threadpool_add_task(&pool, ip_recv, (void *)ip_data); // 线程池添加任务
        }
    }

    threadpool_destory(&pool); // 销毁线程池
    close(sockfd);             // 关闭套接字
    return 0;
}
